
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
 */
package meeple;

/**
 *
 * @author rogier
 */
public class Map {
    private int height;
    private int middle_x;
    private int middle_y;

    // Hashtable<Point, Tile> tile_map;
    Tile[][]    tile_map;
    private int width;

    public Map(int width, int height) {

        // tile_map = new Hashtable<Point, Tile>();
        if ((width > 2) && (height > 2)) {
            this.width  = width;
            this.height = height;
            tile_map    = new Tile[this.width][this.height];
            middle_x    = 4;    // this.width / 2;
            middle_y    = 4;    // this.height / 2;
        } else {
            this.width  = 2;
            this.height = 2;
            tile_map    = new Tile[this.width][this.height];
            middle_x    = 1;
            middle_y    = 1;
        }
    }

    public void setRoot(Tile tile) {
        if ((tile_map[middle_x][middle_y] == null)) {
            tile_map[middle_x][middle_y] = tile;
        }
    }

    public Tile getTile(int x, int y) {
        if (inView(x, y) &&!(tile_map[x][y] == null)) {
            return tile_map[x][y];
        } else {
            return null;
        }
    }

    public boolean setTile(Tile tile, int x, int y) {
        if (inView(x, y) && (tile_map[x][y] == null)) {
            if (tileFits(tile, x, y)) {
                tile_map[x][y] = tile;

                return true;
            } else {
                System.out.println("Tile Doesn't fit");
            }
        } else {
            System.out.println("Tile Exists");
        }

        return false;
    }

    public boolean hasTile(int x, int y) {
        return !(tile_map[x][y] == null);
    }

    private boolean tileFits(Tile tile, int x, int y) {
        boolean fit         = false;
        int     empty_tiles = 0;

        // Check if adjecent upper tile exists if it has the correct type
        if ((y - 1 > 0) &&!(tile_map[x][y - 1] == null)) {
            System.out.println("top to bottom " + tile.getTop().toString() + "="
                               + tile_map[x][y - 1].getBottom().toString());
            fit = tile.getTop() == tile_map[x][y - 1].getBottom();
        } else {
            empty_tiles++;
        }

        // Check if adjecent left tile exists if it has the correct type
        if ((x - 1 > 0) &&!(tile_map[x - 1][y] == null)) {
            System.out.println("left to right " + tile.getLeft().toString() + "="
                               + tile_map[x - 1][y].getRight().toString());
            fit = tile.getLeft() == tile_map[x - 1][y].getRight();
        } else {
            empty_tiles++;
        }

        // Check if adjecent bottom tile exists if it has the correct type
        if ((y + 1 < height) &&!(tile_map[x][y + 1] == null)) {
            System.out.println("bottom to top " + tile.getBottom().toString() + "="
                               + tile_map[x][y + 1].getTop().toString());
            fit = tile.getBottom() == tile_map[x][y + 1].getTop();
        } else {
            empty_tiles++;
        }

        // Check if adjecent right tile exists if it has the correct type
        if ((x + 1 < width) &&!(tile_map[x + 1][y] == null)) {
            System.out.println("right to left " + tile.getRight().toString() + "="
                               + tile_map[x + 1][y].getLeft().toString());
            fit = tile.getRight() == tile_map[x + 1][y].getLeft();
        } else {
            empty_tiles++;
        }

        return fit && (empty_tiles < 4);
    }

    private boolean inView(int x, int y) {
        return (x >= 0) && (y >= 0) && (x < getWidth()) && (y < getHeight());
    }

    /**
     * @return the width
     */
    public int getWidth() {
        return width;
    }

    /**
     * @return the height
     */
    public int getHeight() {
        return height;
    }

    boolean setMeeple(Position p, Player pl, int x, int y) {
        tile_map[x][y].setMeeple(p);
        tile_map[x][y].setOwner(pl);

        return true;
    }

    // public int followRoad(int x, int y ,Direction d){
    // if(tile_map[x][y].getCenter() == TileType.cloister || tile_map[x][y].getCenter() == TileType.junction)
    //
    // return 0;
    // }
    private boolean isMeepleAllowed(Position p, Player pl, int x, int y) {
        boolean result = true;

        switch (tile_map[x][y].getTypes(p)) {
        case junction :
            result = false;

            break;

        case road :
            result = isMeepleAllowedonRoad(p, pl, x, y);

            break;

        case field :
            result = isMeepleAllowedinField(p, pl, x, y);

            break;

        case cloister :
            if (tile_map[x][y].getOwner() == null) {
                result = true;
            }

            break;

        case shield :
        case city :
            result = isMeepleAllowedinCity(p, pl, x, y);

            break;

        default :
            result = true;
        }

        return result;
    }

    private boolean isMeepleAllowedonRoad(Position p, Player pl, int x, int y) {
        return true;
    }

    private boolean isMeepleAllowedinField(Position p, Player pl, int x, int y) {
        return true;
    }

    private boolean isMeepleAllowedinCity(Position p, Player pl, int x, int y) {
        return true;
    }

    private void followRoad(Result r, Position p, Player pl, int x, int y) {
        if (tile_map[x][y].isVisited()) {
            return;
        }

        if ((tile_map[x][y].getTypes(Position.center) == TileType.junction)
                || (tile_map[x][y].getTypes(Position.center) == TileType.cloister)
                || (tile_map[x][y].getTypes(Position.center) == TileType.city)) {
            r.meeples += (tile_map[x][y].getMeeple() == p)
                         ? 1
                         : 0;
            r.lenght  += 1;
            r.closed  = true;

            return;
        }

        tile_map[x][y].setVisited(true);

        int result = 0;

        for (Position pos : Position.values()) {
            if (pos != Position.none) {
                if (tile_map[x][y].getTypes(pos) == TileType.road) {
                    if (inView(x + pos.X(), y + pos.Y()) && (tile_map[x + pos.X()][y + pos.Y()] != null)
                            && (tile_map[x + pos.X()][y + pos.Y()].isVisited() == false)) {
                        r.lenght  += 1;
                        r.meeples += (tile_map[x][y].getMeeple() == pos)
                                     ? 1
                                     : 0;
                        r.closed  = false;
                        followRoad(r, Position.Opposite(pos), pl, x + pos.X(), y + pos.Y());
                    }
                }
            }
        }

        tile_map[x][y].setVisited(false);

        return;
    }

    class Result {
        boolean closed;
        int     lenght;
        int     meeples;
    }
}


//~ Formatted by Jindent --- http://www.jindent.com
